package com.stu.status;

import java.lang.ref.WeakReference;
import java.util.Timer;
import java.util.TimerTask;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

import com.stu.aq.*;
import com.stu.aq.CommandFragment.FragmentState;
import com.stu.aq.CommandFragment.OnCommandListener;
import com.stu.usb.*;

public class VersionFragment extends DialogFragment implements SerialIOManager.Listener {
	private TableLayout table;
	private String status;
	private boolean isAlive;
	private int lineCount, startIndex;
	private View view;
	private Timer timer;
	private OnCommandListener mListener;
	private VersionStatusManager statusManager;
	private String values[];

	/*
	 * VersionStatusData and VersionStatusManager are used
	 * to communicate with the UI thread from the IO thread.
	 */
	private class VersionStatusData {
		public WeakReference<VersionFragment>	fragment;
		
		public VersionStatusData( VersionFragment f ) {
			fragment = new WeakReference<VersionFragment>( f );
		}
	}

	private class VersionStatusManager {
		private Handler h;
		
		@SuppressLint("HandlerLeak")
		public VersionStatusManager() {
			h = new Handler( Looper.getMainLooper() ) {
				@Override
				public void handleMessage(Message msg) {
					VersionStatusData d = (VersionStatusData)msg.obj;
					VersionFragment vf = d.fragment.get();
					if( vf != null )
						vf.updateUI();
				}
				
			};
		}
		
		public void handleState( VersionStatusData d ) {
			Message m = h.obtainMessage(0, d);
			m.sendToTarget();
		}
	}

	public VersionFragment() {
		mListener = null;
		isAlive = false;
		lineCount = 0;
		startIndex = -1;
		statusManager = new VersionStatusManager();
	}

	@Override
	public Dialog onCreateDialog(Bundle savedInstanceState) {
		AlertDialog.Builder builder = new AlertDialog.Builder( getActivity() );
		LayoutInflater inflater = getActivity().getLayoutInflater();
		view = inflater.inflate( R.layout.version, null );
		table = (TableLayout)view.findViewById( R.id.versionTable );
		if( values != null ) {
			for( int i = 1; i < values.length; i++ ) {
				TableRow r = new TableRow( view.getContext() );
				r.setGravity( Gravity.CENTER_HORIZONTAL );
				TextView t = new TextView( view.getContext() );
				if( values[i].indexOf(':') != -1 ) {
					String pair[] = values[i].split( ":" );
					t.setText( pair[0].trim() );
					r.addView( t );
					t = new TextView( view.getContext() );
					t.setPadding( 10, 0, 0, 0 );
					t.setText( pair[1].trim() );
				} else
					t.setText( values[i].trim() );
				r.addView( t );
				table.addView( r );
			}
		}
		builder.setView( view );
		builder.setTitle( "Version" );
		builder.setPositiveButton( android.R.string.ok, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		return builder.create();
	}

	@Override
	public void onNewData(final byte[] data) {
		if( status == null )
			status = new String( data );
		else
			status += new String( data );
		// The first result is the number of status lines
		if( lineCount == 0 ) {
			startIndex = status.indexOf( '\n' );
			if( startIndex == -1 )
				return;		// don't have the first line yet
			try {
				// each line ends with \r\n
				lineCount = Integer.parseInt( status.substring(0, startIndex-1) );
			} catch( NumberFormatException e ) {
				mListener.OnCommandError( R.id.versionView, new AQException(VersionFragment.class.getSimpleName() +
				  ": NumberFormatException: " + e.getMessage()) );
				status = null;
				return;
			}
		}
		values = status.split( "\n" );
		// include the line count in the total response count
		if( values.length != (lineCount + 1) )
			return;
		status = null;
		timer.cancel();
		isAlive = true;		// we got a response
		statusManager.handleState( new VersionStatusData(this) );
	}

	@Override
	public void onRunError(Exception e) {
	}

	public void update( SerialIOManager m, OnCommandListener l ) {
		mListener = l;
		isAlive = false;
		status = null;
		lineCount = 0;
		m.setListener( this );
		String s = "#";
		m.writeAsync( s.getBytes() );
		// Make sure we got the status within 3 seconds
		timer = new Timer();
		TimerTask tt = new TimerTask() {
			@Override
			public void run() {
				checkIfAlive();
			}
		};
		timer.schedule( tt, 3000 );
	}

	private void updateUI() {
		mListener.OnCommandComplete( R.id.versionView, FragmentState.UPDATING );
	}
	
	private void checkIfAlive() {
		if( !isAlive )
			mListener.OnCommandError( getId(), new AQException("No response from AeroQuad") );
	}
}
